package cn.iocoder.yudao.module.vos.service.marketingscore.app;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.vos.controller.app.marketingscore.vo.MarketingScorePhoneMd5RespVO;
import cn.iocoder.yudao.module.vos.dal.dataobject.marketinglistlog.MarketingListLogDO;
import cn.iocoder.yudao.module.vos.dal.dataobject.secretaccount.SecretAccountDO;
import cn.iocoder.yudao.module.vos.dal.dataobject.secretaccountproductprice.SecretAccountProductPriceDO;
import cn.iocoder.yudao.module.vos.dal.mysql.marketinglistlog.MarketingListLogMapper;
import cn.iocoder.yudao.module.vos.service.secretaccount.SecretAccountService;
import cn.iocoder.yudao.module.vos.service.secretaccount.vo.ChargeResult;
import cn.iocoder.yudao.module.vos.service.secretaccountproductprice.SecretAccountProductPriceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class MarketingScoreApiServiceImpl implements MarketingScoreApiService {

    /** 分页接口权限（读取名单） */
    private static final String PERMISSION_PAGE   = "marketing_list_acquisition";
    /** 更新接口权限（更新名单响应状态） */
    private static final String PERMISSION_UPDATE = "marketing_list_update";

    private final SecretAccountService secretAccountService;
    private final MarketingListLogMapper marketingListLogMapper;
    private final SecretAccountProductPriceService secretAccountProductPriceService;

    @Override
    public PageResult<MarketingScorePhoneMd5RespVO> pageTopByDay(String appSecret, PageParam pageParam, String ip, LocalDate targetDate) {
        // 1) 账号校验（权限 + 状态 + 余额>0）—— 使用读取权限
        SecretAccountDO account = secretAccountService.checkAndGetAccount(appSecret, PERMISSION_PAGE);

        // 2) 分页
        int pageNo = pageParam.getPageNo() == null ? 1 : pageParam.getPageNo();
        int pageSize = pageParam.getPageSize() == null ? 10 : pageParam.getPageSize();
        int offset = (pageNo - 1) * pageSize;

        // 3) 查询名单（按租户 + list_date）
        List<MarketingListLogDO> logs =
                marketingListLogMapper.selectByTenantAndCreateDate(targetDate, account.getRechargeTenantId(), offset, pageSize);
        Long total =
                marketingListLogMapper.countByTenantAndCreateDate(targetDate, account.getRechargeTenantId());

        // 4) 读取定价（读取接口定价）
        SecretAccountProductPriceDO priceDO = secretAccountProductPriceService.getSecretAccountProductPrice(PERMISSION_PAGE);
        BigDecimal unitPrice = (priceDO != null && priceDO.getUnitPrice() != null) ? priceDO.getUnitPrice() : BigDecimal.ZERO;

        // 5) 是否扣费（有返回数据且单价>0）
        boolean shouldCharge = unitPrice.compareTo(BigDecimal.ZERO) > 0 && !logs.isEmpty();

        // 6) 记账
        String url = "/data/v1/score/page";
        String paramsMasked = "pageNo=" + pageNo + "&pageSize=" + pageSize + "&date=" + targetDate + "&appSecret=***";
        String respBrief = "{size:" + logs.size() + ", charged:" + (shouldCharge ? "Y" : "N") + "}";
        String requestNo = System.currentTimeMillis() + "_" + UUID.randomUUID().toString().replace("-", "");
        ChargeResult cr = secretAccountService.chargeAndLog(
                account, unitPrice, shouldCharge, url, paramsMasked, PERMISSION_PAGE, respBrief, requestNo, ip
        );

        // 7) 仅返回 phoneMd5
        List<MarketingScorePhoneMd5RespVO> list = logs.stream()
                .map(log -> MarketingScorePhoneMd5RespVO.builder().phoneMd5(log.getPhoneMd5()).build())
                .collect(Collectors.toList());

        return new PageResult<>(list, total);
    }

    /** /update：使用更新权限进行账号校验与定价 */
    @Override
    public boolean updateResponseWithCharge(String appSecret,
                                            String phoneMd5,
                                            Integer responseState,
                                            LocalDateTime responseTime,
                                            String ip) {
        // 1) 账号校验（权限 + 状态 + 余额>0）
        SecretAccountDO account = secretAccountService.checkAndGetAccount(appSecret, PERMISSION_UPDATE);

        // 2) 查询该手机号在该租户下的所有记录
        List<MarketingListLogDO> existingList =
                marketingListLogMapper.selectListByPhoneMd5AndTenant(phoneMd5, account.getRechargeTenantId());

        // 2.1) 规则判断：只要存在任意一条不为 2，则需要“全部更新”；反之（全部为 2）则不更新
        boolean needUpdate = (existingList == null || existingList.isEmpty())
                || existingList.stream().anyMatch(x -> x.getResponseState() == null || x.getResponseState() != 2);

        if (!needUpdate) {
            log.warn("[update] tenant={}, phoneMd5={} 该手机号所有记录均为成交(2)，按规则不更新、不扣费。匹配条数={}",
                    account.getRechargeTenantId(), maskMd5(phoneMd5),
                    existingList == null ? 0 : existingList.size());
            return false;
        }

        // 3) 执行“全部更新”（按 tenantId + phoneMd5 命中所有记录）
        int rows = marketingListLogMapper.updateResponseStateAndTime(
                phoneMd5, account.getRechargeTenantId(), responseState, responseTime, account.getId());
        boolean updated = rows > 0;

        // 4) 定价与扣费（仅在发生更新时考虑扣费）
        SecretAccountProductPriceDO priceDO = secretAccountProductPriceService.getSecretAccountProductPrice(PERMISSION_UPDATE);
        BigDecimal unitPrice = (priceDO != null && priceDO.getUnitPrice() != null) ? priceDO.getUnitPrice() : BigDecimal.ZERO;
        boolean shouldCharge = updated && unitPrice.compareTo(BigDecimal.ZERO) > 0;

        // 5) 记账与日志
        String url = "/data/v1/score/update";
        String paramsMasked = "phoneMd5=" + maskMd5(phoneMd5)
                + "&responseState=" + responseState
                + "&responseTime=" + responseTime
                + "&appSecret=***";
        String respBrief = "{updated:" + (updated ? "Y" : "N") + ", rows:" + rows + ", charged:" + (shouldCharge ? "Y" : "N") + "}";
        String requestNo = System.currentTimeMillis() + "_" + UUID.randomUUID().toString().replace("-", "");
        secretAccountService.chargeAndLog(
                account, unitPrice, shouldCharge, url, paramsMasked, PERMISSION_UPDATE, respBrief, requestNo, ip
        );

        return updated;
    }


    /** 简单脱敏：保留前 6 位 */
    private String maskMd5(String md5) {
        if (StrUtil.isBlank(md5) || md5.length() <= 6) return "***";
        return md5.substring(0, 6) + "****";
    }

}
